﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using BCCommon;
using BCEntity.Chats;

namespace BCData.Chats
{
    public class ThreadData : IThreadData
    {
        private readonly IDatabaseContext databaseContext;

        public ThreadData(IDatabaseContext databaseContext)
        {
            this.databaseContext=databaseContext;
        }

        public Task<IEnumerable<ThreadEntity>> GetThreadsAsync(string userId)
        {
            const string sql = @"SELECT A.*
FROM chat_thread A INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
WHERE B.ParticipantUserId = ?UserId
ORDER BY A.LastChatTime DESC";

            return this.databaseContext.Slave.QueryAsync<ThreadEntity>(sql, new { userId });
        }

        public Task<ThreadEntity> GetThreadAsync(long threadId)
        {
            string sql = typeof(ThreadEntity).GetSelectSqlByPrimaryKeys();

            return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { threadId });
        }

        public Task<ThreadEntity> InsertAsync(ThreadEntity entity)
        {
            return this.databaseContext.Master.InsertAsync(entity, this.databaseContext.Transaction);
        }

        public Task<ThreadEntity> UpdateAsync(ThreadEntity entity)
        {
            return this.databaseContext.Master.UpdateAsync(entity, this.databaseContext.Transaction);
        }

        public Task<ThreadEntity> GetPrivateThreadAsync(string participantUserId1, string participantUserId2)
        {
            const string sql = @"SELECT A.*
FROM chat_thread A
INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
INNER JOIN chat_threadparticipant C ON A.ThreadId = C.ThreadId
WHERE A.Type = 'Private' AND A.`Status` = 'Chating'
AND B.`Status` = 'Joined' AND B.ParticipantUserId = ?participantUserId1'
AND C.`Status` = 'Joined' AND C.ParticipantUserId = ?participantUserId2";

            return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { participantUserId1, participantUserId2 });
        }

        public Task<ThreadEntity> GetCustomerServiceThreadAsync(string businessType, string referenceNumber, string participantUserId)
        {
            if (string.IsNullOrWhiteSpace(referenceNumber))
            {
                const string sql = @"SELECT A.*
FROM chat_thread A
INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
WHERE A.Type = 'CustomerService' AND A.`Status` = 'Chating' AND A.BusinessType = ?BusinessType AND A.ReferenceNumber IS NULL
AND B.`Status` = 'Joined' AND B.ParticipantUserId = ?ParticipantUserId";

                return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { businessType, participantUserId });
            }
            else
            {
                const string sql = @"SELECT A.*
FROM chat_thread A
INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
WHERE A.Type = 'CustomerService' AND A.`Status` = 'Chating' AND A.BusinessType = ?BusinessType AND A.ReferenceNumber = ?ReferenceNumber
AND B.`Status` = 'Joined' AND B.ParticipantUserId = ?ParticipantUserId";

                return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { businessType, referenceNumber, participantUserId });
            }
        }

        public Task<ThreadEntity> GetCustomerServiceThreadAsync(string businessType, string referenceNumber, string participantUserId1, string participantUserId2)
        {
            if (string.IsNullOrWhiteSpace(referenceNumber))
            {
                const string sql = @"SELECT A.*
FROM chat_thread A
INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
INNER JOIN chat_threadparticipant C ON A.ThreadId = C.ThreadId
WHERE A.Type = 'CustomerService' AND A.`Status` = 'Chating' AND A.BusinessType = ?BusinessType AND A.ReferenceNumber IS NULL
AND B.`Status` = 'Joined' AND B.ParticipantUserId = ?ParticipantUserId1
AND C.`Status` = 'Joined' AND C.ParticipantUserId = ?ParticipantUserId2";

                return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { businessType, participantUserId1, participantUserId2 });
            }
            else
            {
                const string sql = @"SELECT A.*
FROM chat_thread A
INNER JOIN chat_threadparticipant B ON A.ThreadId = B.ThreadId
INNER JOIN chat_threadparticipant C ON A.ThreadId = C.ThreadId
WHERE A.Type = 'CustomerService' AND A.`Status` = 'Chating' AND A.BusinessType = ?BusinessType AND A.ReferenceNumber = ?ReferenceNumber
AND B.`Status` = 'Joined' AND B.ParticipantUserId = ?ParticipantUserId1
AND C.`Status` = 'Joined' AND C.ParticipantUserId = ?ParticipantUserId2";

                return this.databaseContext.Slave.QueryFirstOrDefaultAsync<ThreadEntity>(sql, new { businessType, referenceNumber, participantUserId1, participantUserId2 });
            }
        }
    }
}
